/*******************************************************
  > Copyright (C) 2024 ==iot== All rights reserved.
  > File Name: 1.c
  > Author: wyf
  > Created Time: 2024年08月08日 星期四 16时39分17秒
 ***************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h> //目录名获取配合DIR
#include <assert.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h> //文件控制操作
#include <sys/types.h> //获取pid等
#include <sys/wait.h> //等待子进程结束
#include <time.h> //时间获取
#include <sys/ipc.h> //进程通信
#include <sys/msg.h> //消息队列
#include <sys/shm.h> //共享内存
#include <signal.h> //信号处理
#include <pthread.h> //线程
#include <semaphore.h>

int flag = 0;

typedef struct queue {
	int data;           //数据
	struct queue* next;    
	sem_t mutex_write;	//信号量--写
	sem_t mutex_read;//信号量--读
	pthread_mutex_t  mutex;//互斥锁
	struct queue* head;
} Queue;

// 初始化头结点
Queue* create_queue() {
	Queue* head = (Queue*)malloc(sizeof(Queue)); 
	head->next = NULL;  
	return head;    
}

// 入队
void push(int data, Queue* head) {
	Queue* newNode = (Queue*)malloc(sizeof(Queue)); 
	newNode->data = data;      

	Queue* p = head; 
	while (p->next != NULL) { 
		p = p->next;
	}    


	p->next = newNode;      
	newNode->next = NULL;   
	p = newNode;
}

// 获取队列头的第一个数据
int front(Queue* head) {
	if (head->next == NULL) {   
		printf("Queue is empty\n");
		return -1;           
	}
	return head->next->data;    
}

// 出队
void pop(Queue* head) {
	if (head->next == NULL) {   
		printf("队列是空的!\n");
		return;
	}
	Queue* p = head->next; 
	head->next = head->next->next; 
	free(p); 
}

// 返回队列的大小
int size(Queue* head) {
	int count = 0;     
	Queue* p = head->next; 
	while (p != NULL) {  
		count++;    
		p = p->next;   
	}
	return count;  
}

// 销毁队列
void destroy_queue(Queue* head) {
	Queue* p = head;    
	while (p != NULL) { 
		Queue* temp = p;
		p = p->next; 
		free(temp);  
	}
}


//线程1--生产者
void *fun1(void *arg)
{
	Queue* p = (Queue*)arg;

	while(flag == 0)
	{
		printf("please input data:\n");
		scanf("%d",&p->data);			//会卡在这块，应该多输入一个，才会让线程执行下一句！！！

		sem_wait(&p->mutex_write);
		if(flag ==1)				//退出线程
		{
			break;
		}
		pthread_mutex_lock(&p->mutex);

		push(p->data,p->head);
		sem_post(&p->mutex_read);
		printf("入队数据是：%d\n",p->data);
		pthread_mutex_unlock(&p->mutex);
	}
}




//线程2--消费者
void *fun2(void *arg)
{
	Queue* p = (Queue*)arg;

	while(flag == 0)
	{

		sem_wait(&p->mutex_read);
		if(flag ==1)
		{
			break;
		}
		
		pthread_mutex_lock(&p->mutex);

		p->data = front(p->head);
		//pop(p->head);
		sem_post(&p->mutex_write);

		pthread_mutex_unlock(&p->mutex);

		printf("队列中第一个元素是：%d\n",p->data);
		
	}
}

//扫尾工作
void fun3(int sig)
{
	flag = 1;

	printf("我已完成扫尾工作，再输入一个值结束scanf，结束程序！\n");

}


int main() {
	pthread_t tid1 = 0,tid2 = 0;
	int ret = 0;
	 Queue res;
	
	memset(&res,0,sizeof(Queue));

	signal(SIGINT,fun3);


	sem_init(&res.mutex_write,0,3);
	sem_init(&res.mutex_read,0,0);
	pthread_mutex_init(&res.mutex,NULL);
	res.head = create_queue();  

	ret = pthread_create(&tid1,NULL,fun1,&res);
	if(ret != 0)
	{
		perror("pthread_create");
		exit(-1);
	}

	ret = pthread_create(&tid2,NULL,fun2,&res);
	if(ret != 0)
	{
		perror("pthread_create");
		exit(-1);
	}
									
	while(flag == 0);						//让进程一直卡在这判断flag！！！！！！！！！！
{

}
								//然后再解锁！！！
	sem_post(&res.mutex_read); 
	sem_post(&res.mutex_write);


	pthread_join(tid1,NULL);	
	pthread_join(tid2,NULL);
	
	printf("队列大小是： %d\n", size(res.head)); // 显示队列大小

	sem_destroy(&res.mutex_write);
	sem_destroy(&res.mutex_read);

	destroy_queue(res.head);
	printf("已销毁队列\n");

	return 0;
}
